#include "https_connection_pool.h"

HttpsConnectionPool::HttpsConnectionPool(boost::asio::io_context& ioc,
                                         boost::asio::ssl::context& ssl_ctx,
                                         const std::string& host,
                                         const std::string& port,
                                         size_t pool_size)
    : io_context_(ioc),
      ssl_context_(ssl_ctx),
      host_(host),
      port_(port),
      next_index_(0)
{
    // 预先创建连接对象
    for (size_t i = 0; i < pool_size; ++i) {
        auto conn = std::make_shared<HttpsConnection>(io_context_, ssl_context_, host_, port_);
        try {
            conn->connect(); // 同步建立连接
            connections_.push_back(conn);
            available_.push(conn);
        } catch (std::exception& e) {
            std::cerr << "HttpsConnectionPool connect failed: " << e.what() << std::endl;
        }
    }

    std::cout << "HttpsConnectionPool Initialized with "
              << connections_.size() << " connections\n";
}

void HttpsConnectionPool::asyncSendRequest(const std::string& method,
                                           const std::string& target,
                                           const std::string& body,
                                           const std::vector<std::pair<std::string,std::string>>& headers,
                                           ResponseCallback callback)
{
    std::shared_ptr<HttpsConnection> conn = getAvailableConnection();
    if (!conn) {
        std::cerr << "HttpsConnectionPool no available connection\n";
        boost::beast::error_code ec = boost::asio::error::try_again;
        boost::asio::post(io_context_, [callback, ec]() { callback(ec, ""); });
        return;
    }

    auto self = shared_from_this();

    conn->asyncSendRequest(method, target, body, headers,
        [this, self, conn, callback](const boost::beast::error_code& ec, const std::string& resp) {
            // 释放连接回池中
            if (!ec) {
                std::lock_guard<std::mutex> lock(mutex_);
                available_.push(conn);
            } else {
                std::cerr << "HttpsConnectionPool connection error: " << ec.message() << "\n";
                tryReconnect(conn);
            }
            callback(ec, resp);
        });
}

//同步发送请求，返回响应
std::string HttpsConnectionPool::syncSendRequest(const std::string& method,
                                         const std::string& target,
                                         const std::string& body,
                                         const std::vector<std::pair<std::string,std::string>>& headers)
{
    std::shared_ptr<HttpsConnection> conn = getAvailableConnection();
    if (!conn) {
        throw std::runtime_error("HttpsConnectionPool no available connection");
    }

    try {
        std::string response = conn->sendRequest(method, target, body, headers);
        // 释放连接回池中
        std::lock_guard<std::mutex> lock(mutex_);
        available_.push(conn);
        return response;
    } catch (std::exception& e) {
        std::cerr << "HttpsConnectionPool connection error: " << e.what() << "\n";
        tryReconnect(conn);
        throw;
    }
}


std::shared_ptr<HttpsConnection> HttpsConnectionPool::getAvailableConnection() {
    std::lock_guard<std::mutex> lock(mutex_);
    if (available_.empty()) return nullptr;
    auto conn = available_.front();
    available_.pop();
    return conn;
}

void HttpsConnectionPool::tryReconnect(std::shared_ptr<HttpsConnection> conn) {
    boost::asio::post(io_context_, [this, conn]() {
        try {
            conn->connect();
            std::lock_guard<std::mutex> lock(mutex_);
            available_.push(conn);
            std::cout << "HttpsConnectionPool reconnected\n";
        } catch (...) {
            std::cerr << "HttpsConnectionPool reconnect failed\n";
        }
    });
}
